from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from prod.models import *
import jwt
import redis
from shop.settings import SECRET_KEY
from user.views import check_login
from django.core.paginator import Paginator  # Django自带的分页器


# Create your views here.
class ImgView(APIView):
    def get(self, request):
        """获取数据库中的轮播图信息，并返回"""
        img_all = ImgModel.objects.all()

        img_list = [{
            "id": i.id,
            "img_path": i.img_path,
            "desc": i.desc
        } for i in img_all]

        return Response({
            "code": 200,
            "msg": "获取成功",
            "data": img_list
        })


class CateAllView(APIView):
    def get(self, request):
        """根据分类名字，获取到分类下的所有前七个商品"""
        cate_name = request.query_params.get("categoryName")

        cate_info = CateModel.objects.filter(name=cate_name).first()  # 根据分类名字找分类对象。如果没有找到，则返回None

        if cate_info is None:
            return Response({
                "code": 400,
                "msg": "分类不存在"
            })

        goods_all = cate_info.goodsmodel_set.order_by("-count").all()[:7]
        print(goods_all)

        goods_list = [{
            "id": i.id,
            "sku_name": i.sku_name,
            "price": i.price,
            "selling_price": i.selling_price,
            "img": i.img,
            "title": i.title,
            "instruction": i.instruction,
            "count": i.count,
            "stock": i.stock,
            "cate": i.cate.name,
            "online": i.online,
        } for i in goods_all]

        return Response({
            "code": 200,
            "msg": "获取成功",
            "data": goods_list
        })


class HotGoodsView(APIView):
    def get(self, request):
        cate_name = request.query_params.get("categoryName")
        cate_name = cate_name.split(",")

        cate_all = CateModel.objects.filter(name__in=cate_name).all()
        cate_ids = [i.id for i in cate_all]

        goods_all = GoodsModel.objects.filter(cate_id__in=cate_ids).order_by("-count").all()[:7]

        goods_list = [{
            "id": i.id,
            "sku_name": i.sku_name,
            "price": i.price,
            "selling_price": i.selling_price,
            "img": i.img,
            "title": i.title,
            "instruction": i.instruction,
            "count": i.count,
            "stock": i.stock,
            "cate": i.cate.name,
            "online": i.online,
        } for i in goods_all]

        return Response({
            "code": 200,
            "msg": "ok",
            "data": goods_list
        })


class GoodsInfoView(APIView):
    @check_login
    def get(self, request, id):
        """根据ID获取到商品详情的内容"""
        goods_info = GoodsModel.objects.filter(id=id).first()
        user_id = request.user_id

        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在"
            })

        is_collect = GoodsCollectModel.objects.filter(goods_id=id).filter(user_id=user_id).first()

        return Response({
            "code": 200,
            "msg": "ok",
            "data": {
                "id": goods_info.id,
                "sku_name": goods_info.sku_name,
                "price": goods_info.price,
                "selling_price": goods_info.selling_price,
                "img": goods_info.img,
                "title": goods_info.title,
                "instruction": goods_info.instruction,
                "count": goods_info.count,
                "stock": goods_info.stock,
                "cate": goods_info.cate.name,
                "online": goods_info.online,
                "is_collect": bool(is_collect)
            }
        })


class GoodsImgView(APIView):
    def get(self, request, id):
        # 先找到商品
        goods_info = GoodsModel.objects.filter(id=id).first()

        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在"
            })

        goods_img = goods_info.goodsimgmodel_set.all()
        img_list = [{
            "id": i.id,
            "img_path": i.img_path,
            "desc": i.desc,
        } for i in goods_img]

        return Response({
            "code": 200,
            "msg": "ok",
            "data": img_list
        })


class GoodsHistoryView(APIView):
    def get(self, request):
        token = request.headers.get("Token")

        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms="HS256")
        except Exception as e:
            print(e)
            return Response({
                "code": 403,
                "msg": "登录失败"
            })
        user_id = payload["user_id"]

        rds = redis.Redis(host="127.0.0.1", db=2)
        key = "history_%s" % user_id
        ids = rds.lrange(key, 0, -1)

        # 此方法无顺序，不可以使用
        # ids_id = [int(i.decode()) for i in ids]
        # print(ids_id)
        # goods_list = GoodsModel.objects.filter(id__in=ids_id).all()

        goods_list = []
        for i in ids:
            id = i.decode()
            goods_info = GoodsModel.objects.filter(id=id).first()
            if not goods_info:
                continue
            goods_list.append(goods_info)

        g_list = [{
            "id": i.id,
            "sku_name": i.sku_name,
            "price": i.price,
            "selling_price": i.selling_price,
            "img": i.img,
            "title": i.title,
            "instruction": i.instruction,
            "count": i.count,
            "stock": i.stock,
            "online": i.online,
        } for i in goods_list]
        return Response({
            "code": 200,
            "msg": "历史记录获取成功",
            "data": g_list,
        })

    def post(self, request):
        id = request.data.get("id")
        token = request.headers.get("Token")

        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms="HS256")
        except Exception as e:
            print(e)
            return Response({
                "code": 403,
                "msg": "登录失败"
            })
        user_id = payload["user_id"]

        # 增删改查 【redis,五大数据类型】 String List
        rds = redis.Redis(host="127.0.0.1", db=2)
        key = "history_%s" % user_id
        rds.lrem(key, 0, id)  # 先删除
        rds.lpush(key, id)  # 再插入
        rds.ltrim(key, 0, 4)  # 再保留5个历史记录即可

        return Response({
            "code": 200,
            "msg": "历史记录添加成功"
        })


class GoodsCollectView(APIView):

    @check_login
    def post(self, request):
        # 接收参数
        goods_id = request.data.get("productID")
        user_id = request.user_id

        # 校验参数
        goods_info = GoodsModel.objects.filter(id=goods_id).first()
        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在"
            })
        # 判断是否已经收藏
        collect_info = GoodsCollectModel.objects.filter(goods_id=goods_id).filter(user_id=user_id).first()

        # 【增]删改查
        title = ""
        try:

            if not collect_info:
                GoodsCollectModel.objects.create(
                    user_id=user_id,
                    goods_id=goods_id
                )
            else:
                collect_info.delete()
                title = "取消"

        except Exception as e:
            return Response({
                "code": 400,
                "msg": title + "收藏失败"
            })

        return Response({
            "code": 200,
            "msg": title + "收藏成功"
        })

    @check_login
    def get(self, request):
        user_id = request.user_id
        user_info = UserModel.objects.filter(id=user_id).first()
        collect_list = user_info.goodscollectmodel_set.all()

        goods_list = [
            {

                "id": i.id,
                "goods_id": i.goods.id,
                "sku_name": i.goods.sku_name,
                "price": i.goods.price,
                "selling_price": i.goods.selling_price,
                "img": i.goods.img,
                "title": i.goods.title,
                "instruction": i.goods.instruction,
                "count": i.goods.count,
                "stock": i.goods.stock,
                "cate": i.goods.cate.name,
                "online": i.goods.online,
            }
            for i in collect_list
        ]

        return Response({
            "code": 200,
            "msg": "收藏列表获取成功",
            "data": goods_list
        })


class GoodsCartView(APIView):

    @check_login
    def get(self, request):
        """获取购物车中的数据"""
        user_id = request.user_id
        rds = redis.Redis(host="127.0.0.1", db=2)
        cart_ids = rds.hgetall("cart_%s" % user_id)  # 返回值是一个字典。字典的键和值都是bytes类型

        cart_goods = []
        for k in cart_ids:
            v = cart_ids[k]
            k, v = k.decode(), v.decode()

            goods_info = GoodsModel.objects.filter(id=k).first()
            if goods_info is None:
                continue

            check = rds.sismember("cart_select_%s" % user_id, k)

            cart_goods.append({
                "id": "",  # 购物车id
                "productID": k,  # 商品id
                "productName": goods_info.sku_name,  # 商品名称
                "productImg": goods_info.img,  # 商品图片
                "price": goods_info.selling_price,  # 商品价格
                "num": int(v),  # 加购的商品数量
                "maxNum": goods_info.stock,  # 商品限购数量
                "check": check  # 是否勾选
            })

        return Response({
            "code": 200,
            "msg": "购物车数据获取成功",
            "data": cart_goods
        })

    @check_login
    def post(self, request):
        """把商品加入购物车"""
        user_id = request.user_id
        goods_id = request.data.get("productID")

        # 判断商品ID对应的商品是否存在
        goods_info = GoodsModel.objects.filter(id=goods_id).first()
        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在"
            })

        if goods_info.stock == 0:
            return Response({
                "code": 202,
                "msg": "超出库存限制"
            })

        rds = redis.Redis(host="127.0.0.1", db=2)
        key = "cart_%s" % user_id
        # 假设商品不在购物车中
        # 判断商品是否在购物车中？
        if not rds.hexists(key, goods_id):
            rds.hset(key, goods_id, "1")
            rds.close()

            # 返回响应
            return Response({
                "code": 200,
                "msg": "加入购物车成功",
                "data": {
                    "id": "",  # 购物车id
                    "productID": goods_id,  # 商品id
                    "productName": goods_info.sku_name,  # 商品名称
                    "productImg": goods_info.img,  # 商品图片
                    "price": goods_info.selling_price,  # 商品价格
                    "num": 1,  # 加购的商品数量
                    "maxNum": goods_info.stock,  # 商品限购数量
                    "check": False,  # 是否勾选
                }
            })
        else:

            # 判断购物车中的商品数量是否>=库存
            cart_num = rds.hget(key, goods_id)
            cart_num = int(cart_num.decode())  # 购物车中商品数量
            if cart_num >= goods_info.stock:
                return Response({
                    "code": 202,
                    "msg": "超出库存限制"
                })

            # 购物车数量+1
            rds.hincrby(key, goods_id, 1)
            rds.close()

            # 返回响应
            return Response({
                "code": 201,
                "msg": "购物车数量+1"
            })

    @check_login
    def put(self, request):
        """修改购物车的数量"""
        user_id = request.user_id
        goods_id = request.data.get("productID")
        num = request.data.get("num")
        num = int(num)

        # 校验参数
        rds = redis.Redis(host="127.0.0.1", db=2)
        key = "cart_%s" % user_id
        # 校验商品是否在购物车中
        if not rds.hexists(key, goods_id):
            return Response({
                "code": 400,
                "msg": "商品不在购物车中"
            })
        # 如果 num < 1 不可以
        if num < 1:
            return Response({
                "code": 400,
                "msg": "商品数量不能小于1"
            })

        # 如果 num > 库存，不可以
        goods_info = GoodsModel.objects.filter(id=goods_id).first()
        if not goods_info:
            return Response({
                "code": 400,
                "msg": "商品不存在"
            })
        if num > goods_info.stock:
            return Response({
                "code": 400,
                "msg": "商品数量不能超出库存，当前剩余库存%s" % goods_info.stock
            })

        # 修改购物车中商品对应的数量
        rds.hset(key, goods_id, num)
        rds.close()

        # 返回200
        return Response({
            "code": 200,
            "msg": "更新成功"
        })

    @check_login
    def delete(self, request):
        # 接收参数
        goods_id = request.query_params.get("id")
        user_id = request.user_id

        # 校验参数，忽略

        # 增删改查。删除购物车中某个商品
        rds = redis.Redis(host="127.0.0.1", db=2)
        key = "cart_%s" % user_id
        select_key = "cart_selete_%s" % user_id
        rds.hdel(key, goods_id)  # 删除购物车中的商品数据
        rds.srem(select_key, goods_id)  # 删除选中购物车中的数据。防止隐藏BUG

        return Response({
            "code": 200,
            "msg": "删除成功"
        })


class GoodsCartSelectionView(APIView):

    @check_login
    def post(self, request):
        user_id = request.user_id
        check = request.data.get("val")
        rds = redis.Redis(host="127.0.0.1", db=2)
        key = "cart_%s" % user_id
        select_key = "cart_select_%s" % user_id

        goods_id = rds.hkeys(key)
        title = ""
        if check:
            # 要全选.找到购物车中的所有商品ID，把商品ID依次加入购物车选中的集合中即可
            for i in goods_id:
                rds.sadd(select_key, i.decode())

        else:
            # 要取消全选
            title = "取消"
            for i in goods_id:
                rds.srem(select_key, i.decode())

        return Response({
            "code": 200,
            "msg": title + "全选成功"
        })

    @check_login
    def put(self, request):
        goods_id = request.data.get("productID")
        check = request.data.get("val")
        user_id = request.user_id

        # 校验参数
        # 判断当前商品是否在当前用户的购物车中
        rds = redis.Redis(host="127.0.0.1", db=2)
        key = "cart_%s" % user_id
        if not rds.hexists(key, goods_id):
            return Response({
                "code": 400,
                "msg": "商品不在购物车中"
            })

        # 判断当前商品是否已经选中。如果没有选中，则去选中。如果选中，则取消选中
        select_key = "cart_select_%s" % user_id
        title = ""
        if check:  # 商品ID不在选中的集合中，以为着没有选中
            rds.sadd(select_key, goods_id)
        else:
            rds.srem(select_key, goods_id)
            title = "取消"

        rds.close()

        # 返回响应
        return Response({
            "code": 200,
            "msg": title + "选中成功"
        })


class CateView(APIView):
    def get(self, request):
        cate_all = CateModel.objects.all()

        return Response({
            "code": 200,
            "msg": "分类获取成功",
            "data": [{
                "id": i.id,
                "cate_name": i.name,
            } for i in cate_all]
        })


class CateGoodsView(APIView):
    def get(self, request):
        page = request.query_params.get("page", 1)
        page_size = request.query_params.get("page_size", 5)
        id = request.query_params.get("id", 0)
        id = int(id)
        page = int(page)
        page_size = int(page_size)

        # 如果ID为0，说明：获取的是全部的商品
        if id == 0:
            goods_list = GoodsModel.objects.all()
        else:
            cate_info = CateModel.objects.filter(id=id).first()
            if not cate_info:
                return Response({
                    "code": 400,
                    "msg": "分类不存在"
                })

            goods_list = cate_info.goodsmodel_set.all()

        # end = page * page_size
        # begin = (page - 1) * page_size
        #
        # goods_list = goods_list[begin:end]
        try:
            p = Paginator(goods_list, page_size)  # 实例化一个分页器
            p_goods = p.page(page)  # 获取某一页的数据
            p_count = p.count  # 总数据条数
        except Exception as e:
            return Response({
                "code": 200,
                "msg": "商品获取成功",
                "data": []
            })

        return Response({
            "code": 200,
            "msg": "商品获取成功",
            "data": [{
                "id": i.id,
                "sku_name": i.sku_name,
                "price": i.price,
                "selling_price": i.selling_price,
                "img": i.img,
                "title": i.title,
                "instruction": i.instruction,
                "count": i.count,
                "stock": i.stock,
                "cate": i.cate.name,
                "online": i.online,
            } for i in p_goods],
            "count": p_count,
            "page": page,
        })
